﻿using Microsoft.EntityFrameworkCore;
using NewRetail.Application.Components.Platform.Entity;
using NewRetail.Application.Components.Platform.Model;
using NewRetail.Application.Components.Warehouse.Entity;
using NewRetail.Application.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;

namespace NewRetail.Application.Components.Platform
{
    public interface ISupplierSettlementService : IApplicationService
    {
        //Task<PaymentReceipt[]> AttachSuppiler(PaymentReceipt[] data);

        /// <summary>
        /// 供应商统一结算报表
        /// </summary>
        /// <param name="inputDto"></param>
        /// <returns></returns>
        Task<IEnumerable<SupplierUnifiedSettlementShowDto>> GetSupplierUnifiedSettlementInfo(QueryInOutWarehouseDto inputDto);
        /// <summary>
        /// 供应商单门店结算报表
        /// </summary>
        /// <param name="inputDto"></param>
        /// <returns></returns>
        Task<IEnumerable<SupplierSingleSettlementShowDto>> GetSupplierSingleSettlementInfo(QuerySingleSettlementDto inputDto);
    }

    public class SupplierSettlementService : MyApplicationService, ISupplierSettlementService
    {
        //private readonly IRepository<PaymentReceipt> paymentReceipts;
        private readonly IRepository<InOutWarehousing> _inOutWarehousingRepository;

        public SupplierSettlementService(IRepository<InOutWarehousing> inOutWarehousingRepository)
        {
            _inOutWarehousingRepository = inOutWarehousingRepository;
        }

        #region method

        #region 供应商统一结算报表
        /// <summary>
        /// 供应商统一结算报表
        /// </summary>
        /// <param name="inputDto"></param>
        /// <returns></returns>
        public async Task<IEnumerable<SupplierUnifiedSettlementShowDto>> GetSupplierUnifiedSettlementInfo(QueryInOutWarehouseDto inputDto)
        {
            var db = await _inOutWarehousingRepository.GetDbContextAsync();
            var query = db.Set<InOutWarehousing>().AsNoTracking();
            query = query.WhereIf(inputDto.startTime != null, x => x.addTime >= inputDto.startTime.Value);
            query = query.WhereIf(inputDto.endTime != null, x => x.addTime < inputDto.endTime.Value);
            var resultData = await query.GroupBy(x => new { x.warehouseID, x.supplierID })
                .Select(x => new SupplierWarehouseSettlementDto
                {
                    warehouseID = x.Key.warehouseID,
                    supplierID = x.Key.supplierID,
                    settlementAmount = x.Sum(x => x.inOrOut == (int)InOrOutEnum.IN ? (x.price * x.quantity) : -(x.price * x.quantity))
                })
                .OrderBy(x => x.supplierID).ThenBy(x => x.warehouseID)
                //.MaxTake()
                .ToListAsync();
            
            //赋值供应商
            await db.AttachData<Supplier, SupplierWarehouseSettlementDto>(resultData,
                idGetter: x => x.supplierID,
                action: (m, arr) => m.Supplier = arr.FirstOrDefault());
            //赋值仓库/店铺
            await db.AttachData<Warehouse.Entity.Warehouse, SupplierWarehouseSettlementDto>(resultData,
               idGetter: x => x.warehouseID,
               action: (m, arr) => m.Warehouse = arr.FirstOrDefault());
            //转换
            var result = resultData.GroupBy(x => x.supplierID).Select(x => new SupplierUnifiedSettlementShowDto
            {
                supplierID = x.Key,
                warehouseIDs = x.Select(y => y.warehouseID).ToArray(),
                settlementAmounts = x.Select(y => y.settlementAmount).ToArray(),
                totalAmount = x.Sum(y=>y.settlementAmount),
                Supplier = x.Select(y => y.Supplier).FirstOrDefault(),
                Warehouses = x.Select(y => y.Warehouse).ToArray()
            }).ToList();
            //赋值已结算金额
            var paymentReceipt = db.Set<PaymentReceipt>().AsNoTracking();
            foreach(var item in result)
            {
                item.totalSettlementAmount = paymentReceipt.Where(x => x.supplierID == item.supplierID).Sum(s => s.money);
            }
            //var ret = new List<SupplierUnifiedSettlementShowDto>();
            //var warehouseIDs = new string[] { };
            //var settlementAmounts = new decimal[] { };
            //var preSupplierID = "";
            ////遍历处理数据
            //for(int i = 0; i < resultData.Count; i++)
            //{
            //    var currSupplierID = resultData[i].supplierID;
            //    var currWarehouseID = resultData[i].warehouseID;
            //    var currSettlementAmount = resultData[i].settlementAmount;
            //    if (preSupplierID != currSupplierID)
            //    {
            //        warehouseIDs = new string[] { };
            //        settlementAmounts = new decimal[] { };
            //        warehouseIDs.AddFirst(currWarehouseID);
            //        settlementAmounts.AddFirst(currSettlementAmount);
            //        //var supplierUnifiedSettlement = new SupplierUnifiedSettlementShowDto();
            //        //supplierUnifiedSettlement.supplierID = currSupplierID;
            //        ret.Add(new SupplierUnifiedSettlementShowDto
            //        {
            //            supplierID = currSupplierID,
            //            warehouseIDs = warehouseIDs,
            //            settlementAmounts = settlementAmounts,
            //        });

            //    }
            //    else
            //    {
            //        //存在则需要加入数组
            //        warehouseIDs.AddLast(currWarehouseID);
            //        settlementAmounts.AddLast(currSettlementAmount);
            //    }

            //    preSupplierID = currSupplierID;
            //}
            //await db.AttachData<Supplier, SupplierUnifiedSettlementShowDto>(ret,
            //    idGetter: x => x.supplierID,
            //    action: (m, arr) => m.Supplier = arr.FirstOrDefault());
            ////await db.AttachData<Warehouse.Entity.Warehouse[], SupplierUnifiedSettlementShowDto>(ret,
            ////   idGetter: x => x.warehouseIDs,
            ////   action: (m, arr) => m.Warehouse = arr.FirstOrDefault());
            return result;
        }
        #endregion

        #region 供应商单门店结算报表
        /// <summary>
        /// 供应商单门店结算报表
        /// </summary>
        /// <param name="inputDto"></param>
        /// <returns></returns>
        public async Task<IEnumerable<SupplierSingleSettlementShowDto>> GetSupplierSingleSettlementInfo(QuerySingleSettlementDto inputDto)
        {
            var db = await _inOutWarehousingRepository.GetDbContextAsync();
            var query = db.Set<InOutWarehousing>().AsNoTracking();
            query = query.Where(x => x.warehouseID == inputDto.warehouseID);
            query = query.WhereIf(inputDto.startTime != null, x => x.addTime >= inputDto.startTime.Value);
            query = query.WhereIf(inputDto.endTime != null, x => x.addTime < inputDto.endTime.Value);
            var resultData = await query.GroupBy(x => new { x.supplierID })
                .Select(x => new SupplierSingleSettlementShowDto
                {
                    supplierID = x.Key.supplierID,
                    inAmount = x.Sum(x => x.inOrOut == (int)InOrOutEnum.IN ? (x.price * x.quantity) : 0),
                    outAmount = x.Sum(x => x.inOrOut == (int)InOrOutEnum.OUT ? (x.price * x.quantity) : 0)
                })
                .OrderBy(x => x.supplierID)
                //.MaxTake()
                .ToListAsync();

            //赋值供应商
            await db.AttachData<Supplier, SupplierSingleSettlementShowDto>(resultData,
                idGetter: x => x.supplierID,
                action: (m, arr) => m.Supplier = arr.FirstOrDefault());

            return resultData;
        }
        #endregion

        #endregion

        //public async Task<PaymentReceipt[]> AttachSuppiler(PaymentReceipt[] data)
        //{
        //    var db = await this.paymentReceipts.GetDbContextAsync();

        //    await db.AttachData<Supplier, PaymentReceipt>(data, x => x.supplierID, (m, arr) => m.Supplier = arr.FirstOrDefault());

        //    return data;
        //}

    }
}
